Skip to content

feat: multi-iframe session pool, session persistence, i18n, and status indicator#55

Open
nthforsth wants to merge 10 commits into
mtymek:mainfrom
nthforsth:main
Open

feat: multi-iframe session pool, session persistence, i18n, and status indicator#55
nthforsth wants to merge 10 commits into
mtymek:mainfrom
nthforsth:main

Conversation

@nthforsth
Copy link
Copy Markdown

Summary

Four improvements to the session experience:

1. Multi-iframe pool for tab switching (fixes session state loss)

  • Each session now has its own iframe; switching tabs uses CSS display toggle instead of changing iframe.src
  • Preserves model selection, scroll position, input content, and all JS state across tab switches

2. Session persistence across Obsidian restarts

  • Sessions (sessionId, iframeUrl, activeIndex) are saved to plugin data on every mutation (add/close/switch)
  • Restored automatically on next startup via OpenCode's existing session IDs
  • Graceful fallback: creates a new session if no saved data exists

3. Chinese/English language toggle in settings

  • New language setting ("en" | "zh") with full i18n coverage of the settings page
  • Language selector at the top of settings; switching instantly re-renders
  • Easy to extend with more languages via src/settings/i18n.ts

4. Real-time session status indicator

  • Polls GET /session/status every 5s when the server is running
  • Ribbon icon pulses with accent color when any session is busy/retrying
  • Tab bar shows per-session busy (pulsing) or attention (red) state based on live API data

Changed files

File | Change -- | -- src/ui/OpenCodeView.ts | Multi-iframe pool + session persistence + status display src/main.ts | Session save/load + status polling + ribbon icon state src/client/OpenCodeClient.ts | New getSessionStatus() API method src/settings/i18n.ts | New file — en/zh translation map src/settings/SettingsTab.ts | i18n support for all settings text src/types.ts | New language setting field styles.css | Iframe container + ribbon busy animation

Test plan

  • Open multiple sessions, verify model selection persists across tab switches
  • Restart Obsidian, verify sessions are restored with correct active tab
  • Switch settings language between English and 中文
  • Send a message to AI, verify ribbon icon pulses during response
  • Verify tab bar shows busy state during AI processing

Fozi and others added 10 commits May 8, 2026 19:26
Previously, switching tabs modified iframe.src, causing the entire
OpenCode Web UI to reload and lose all JS state (model selection,
scroll position, input content). Now each session has its own iframe,
and switching tabs uses CSS display toggle instead of src navigation,
fully preserving per-session state.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sessions (tab list with sessionId, iframeUrl, activeIndex) are now
saved to plugin data on every mutation (add/close/switch) and restored
when the view reopens after an Obsidian restart. Falls back to creating
a new session if no saved data exists.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New language setting (en/zh) with full i18n support for all settings
UI text. Language selector placed at the top of the settings page;
switching instantly re-renders the page in the chosen language.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Polls GET /session/status every 5 seconds when the server is running.
- Ribbon icon pulses with accent color when any session is busy/retrying
- Tab bar shows busy (pulsing) or attention (red) state per session
- Gracefully starts/stops polling with server lifecycle

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bilingual README with Chinese as primary language. Added fork-specific
feature descriptions (multi-session tabs, session persistence, i18n
settings, real-time status indicator). Updated BRAT install path to
nthforsth/opencode-obsidian.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add killZombieOnPort() in ServerManager: detect unresponsive process
  on the configured port and auto-kill it before spawning a new server
- Simplify WindowsProcess.stop(): use taskkill /F /T for reliable
  process tree termination instead of manual PowerShell child lookup
- Simplify WindowsProcess.killProcessSync(): same /T flag improvement
- Add static findPidOnPort/killPid helpers for both Windows/Posix
- Remove unused dependencies from ContextManager and ViewManager
  (client, getCachedIframeUrl, setCachedIframeUrl, ensureSessionUrl)
- Rename plugin id to 'opencodian'

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add listSessions() and deleteSession() to OpenCodeClient for
  server-side session management via REST API
- Add SessionInfo type for session metadata
- Add history button (clock icon) to tab bar
- Add history panel overlay showing all past sessions sorted by time
- Allow loading any historical session into a new tab with one click
- Allow bulk cleanup of old sessions (excluding currently open ones)
- Show relative timestamps (刚刚/X分钟前/X小时前/X天前)
- Mark currently active sessions with accent dot indicator

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The tab bar has overflow-x: auto which clips absolutely positioned
children. Move the panel from tabBarEl to contentEl and position it
with top: 36px so it appears below the tab bar without being clipped.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When the opencode process dies but the OS kernel still holds the TCP
socket (orphan socket), the previous cleanup logic failed because:
- findPidOnPort returns a stale PID from the dead process
- taskkill fails since the process no longer exists
- New opencode process can't bind to the occupied port

Changes:
- Add processExists() to WindowsProcess and PosixProcess to detect
  dead processes vs orphan sockets
- Add findAvailablePort() for automatic port fallback
- Improve killZombieOnPort() with two-phase strategy:
  1. If process alive → kill + wait 5s
  2. If process dead (orphan socket) → wait up to 15s for OS release
  3. If port still stuck → auto-switch to next available port
- Emit "portChanged" event to persist the new port and update views

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant